selector: Redo from list to array
authorBenjamin Otte <otte@redhat.com>
Thu, 1 Mar 2012 17:33:33 +0000 (18:33 +0100)
committerBenjamin Otte <otte@redhat.com>
Fri, 2 Mar 2012 01:17:09 +0000 (02:17 +0100)
Should save ~30% of memory

gtk/gtkcssselector.c

index 8a52b60acdd77bfdfab8caba73a4c50569ef00e1..1a2b1d48fff7195ddf9a9fc3b57a326fdf26ce95 100644 (file)
@@ -19,6 +19,8 @@
 
 #include "gtkcssselectorprivate.h"
 
+#include <string.h>
+
 #include "gtkcssprovider.h"
 #include "gtkstylecontextprivate.h"
 
@@ -42,7 +44,6 @@ struct _GtkCssSelectorClass {
 struct _GtkCssSelector
 {
   const GtkCssSelectorClass *class;       /* type of check this selector does */
-  GtkCssSelector            *previous;    /* link to next element in selector or NULL if last */
   gconstpointer              data;        /* data for matching:
                                              - interned string for CLASS, NAME and ID
                                              - GUINT_TO_POINTER() for PSEUDOCLASS_REGION/STATE */
@@ -63,7 +64,9 @@ gtk_css_selector_match (const GtkCssSelector *selector,
 static const GtkCssSelector *
 gtk_css_selector_previous (const GtkCssSelector *selector)
 {
-  return selector->previous;
+  selector = selector + 1;
+
+  return selector->class ? selector : NULL;
 }
 
 /* ANY */
@@ -445,16 +448,35 @@ static const GtkCssSelectorClass GTK_CSS_SELECTOR_PSEUDOCLASS_REGION = {
 
 /* API */
 
+static guint
+gtk_css_selector_size (const GtkCssSelector *selector)
+{
+  guint size = 0;
+
+  while (selector)
+    {
+      selector = gtk_css_selector_previous (selector);
+      size++;
+    }
+
+  return size;
+}
+
 static GtkCssSelector *
 gtk_css_selector_new (const GtkCssSelectorClass *class,
-                      GtkCssSelector            *previous,
+                      GtkCssSelector            *selector,
                       gconstpointer              data)
 {
-  GtkCssSelector *selector;
+  guint size;
+
+  size = gtk_css_selector_size (selector);
+  selector = g_realloc (selector, sizeof (GtkCssSelector) * (size + 1) + sizeof (gpointer));
+  if (size == 0)
+    selector[1].class = NULL;
+  else
+    memmove (selector + 1, selector, sizeof (GtkCssSelector) * size + sizeof (gpointer));
 
-  selector = g_slice_new0 (GtkCssSelector);
   selector->class = class;
-  selector->previous = previous;
   selector->data = data;
 
   return selector;
@@ -655,9 +677,9 @@ try_parse_name (GtkCssParser   *parser,
 
 static GtkCssSelector *
 parse_simple_selector (GtkCssParser   *parser,
-                       GtkCssSelector *previous)
+                       GtkCssSelector *selector)
 {
-  GtkCssSelector *selector = previous;
+  guint size = gtk_css_selector_size (selector);
   
   selector = try_parse_name (parser, selector);
 
@@ -668,12 +690,12 @@ parse_simple_selector (GtkCssParser   *parser,
         selector = parse_selector_class (parser, selector);
       else if (_gtk_css_parser_try (parser, ":", FALSE))
         selector = parse_selector_pseudo_class (parser, selector);
-      else if (selector == previous)
+      else if (gtk_css_selector_size (selector) == size)
         {
           _gtk_css_parser_error (parser, "Expected a valid selector");
           if (selector)
             _gtk_css_selector_free (selector);
-          selector = NULL;
+          return NULL;
         }
       else
         break;
@@ -709,10 +731,7 @@ _gtk_css_selector_free (GtkCssSelector *selector)
 {
   g_return_if_fail (selector != NULL);
 
-  if (selector->previous)
-    _gtk_css_selector_free (selector->previous);
-
-  g_slice_free (GtkCssSelector, selector);
+  g_free (selector);
 }
 
 void